package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDto;
import com.zzyl.entity.Device;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {

    private static final Logger log = LoggerFactory.getLogger(DeviceServiceImpl.class);
    @Resource
    Client client;

    @Resource
    private DeviceMapper deviceMapper;

    @Value("${zzyl.aliyun.iotInstanceId}")
    private String iotInstanceId;

    // 单个注册设备
    @Override
    public void registerDevice(DeviceDto deviceDto) throws Exception {
        //请求IOT中新增设备
//        RegisterDeviceRequest registerDeviceRequest = new RegisterDeviceRequest();
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setProductKey(deviceDto.getProductKey());
        registerDeviceRequest.setIotInstanceId(iotInstanceId);
        RegisterDeviceResponse registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        //是否新增成功
        if (!registerDeviceResponse.getBody().getSuccess()) {
            throw new Exception("新增设备失败");
        }
        //查询产品名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(iotInstanceId);
        QueryProductResponse queryProductResponse = client.queryProduct(queryProductRequest);
        String productName = queryProductResponse.getBody().getData().getProductName();
        //新增设备
        Device device = new Device();
        BeanUtils.copyProperties(deviceDto, device);
        //设备id
        device.setDeviceId(registerDeviceResponse.getBody().getData().getIotId());
        //备注名称
        device.setNoteName(deviceDto.getNickname());
        //产品key
        device.setProductId(deviceDto.getProductKey());
        //产品名称
        device.setProductName(productName);
        //绑定位置
        device.setBindingLocation(deviceDto.getBindingLocation().toString());
        //判断设备接入类别
        if(Objects.equal(device.getLocationType(), 0)) {
            device.setPhysicalLocationType(-1);
        }
        //添加设备信息到数据库
        try {
            deviceMapper.insert(device);
            log.info("添加设备成功");
        } catch (Exception e) {
            //删除IOT中的设备
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(iotInstanceId);
            deleteDeviceRequest.setProductKey(device.getProductKey());
            deleteDeviceRequest.setDeviceName(device.getDeviceName());
            deleteDeviceRequest.setIotId(device.getDeviceId());
            client.deleteDevice(deleteDeviceRequest);
            throw new RuntimeException("该老人/位置已绑定该产品，请重新选择");
        }
    }

//    @Override
//    public void updateDevice(DeviceDto deviceDto) throws Exception {
//
//    }

    @Override
    public void updateDevice(DeviceDto deviceDto) throws Exception {
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(iotInstanceId);
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = client.batchUpdateDeviceNickname(request);
        // 保存位置
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            // 保存位置
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            device.setProductId(deviceDto.getProductKey());
            device.setNoteName(deviceDto.getNickname());
            Device device1 = deviceMapper.selectByPrimaryKey(device.getId());
            if (ObjectUtil.isEmpty(device1)) {
                device.setDeviceId(deviceDto.getIotId());
                device.setNoteName(deviceDto.getNickname());
                device.setProductId(deviceDto.getProductKey());
                device.setDeviceId(deviceDto.getIotId());
                deviceMapper.insert(device);
                return;
            }
            try {
                deviceMapper.updateByPrimaryKeySelective(device);
            }catch (Exception e) {
                throw new BaseException("该老人/位置已绑定该产品，请重新选择");
            }
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());
    }


    /**
     * 查询设备
     */
    @Override
    public PageResponse<DeviceVo> queryDevice(QueryDeviceRequest request) throws Exception {
        //根据产品查询设备列表
        request.setIotInstanceId(iotInstanceId);
        QueryDeviceResponse queryDeviceResponse = client.queryDevice(request);
        if (!queryDeviceResponse.getBody().getSuccess()) {
            throw new Exception("查询设备失败");
        }
        //取出所有的设备id
        List<QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo> deviceInfoList = queryDeviceResponse.getBody().getData().getDeviceInfo();
        List<String> deviceIdList = deviceInfoList.stream().map(QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo::getIotId)
            .collect(Collectors.toList());
        //根据id集合到DB中查询所有设备
        List<DeviceVo> deviceVos = deviceMapper.selectByDeviceIds(deviceIdList);
        //整合数据
        List<DeviceVo> deviceResult = new ArrayList<>();
        Map<String, DeviceVo> deviceVoMap = deviceVos.stream().collect(Collectors.toMap(DeviceVo::getDeviceId, deviceVo -> deviceVo));
        deviceInfoList.forEach(deviceInfo -> {
            DeviceVo deviceVo = deviceVoMap.get(deviceInfo.getIotId());
            if (deviceVo != null) {
                BeanUtils.copyProperties(deviceInfo, deviceVo);
                deviceResult.add(deviceVo);
            }
        });
        return PageResponse.of(deviceResult, request.getCurrentPage(), request.getPageSize(), (long) queryDeviceResponse.getBody().getPageCount(), (long)queryDeviceResponse.getBody().getTotal());
    }




    /**
     * 查询指定设备的详细信息
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) throws Exception {
        request.setIotInstanceId(iotInstanceId);
        QueryDeviceDetailResponse queryDeviceDetailResponse = client.queryDeviceDetail(request);
        if (Boolean.FALSE.equals(queryDeviceDetailResponse.getBody().getSuccess())) {
            throw new Exception(queryDeviceDetailResponse.getBody().getErrorMessage());
        }
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData deviceData = queryDeviceDetailResponse.getBody().getData();
        DeviceVo deviceVo = new DeviceVo();
        BeanUtils.copyProperties(deviceData, deviceVo);
        List<DeviceVo> devices = deviceMapper.selectByDeviceIds(Lists.newArrayList(deviceData.getIotId()));
        if (CollUtil.isNotEmpty(devices)) {
            BeanUtil.copyProperties(devices.get(0), deviceVo, CopyOptions.create().ignoreNullValue());
            deviceVo.setIotId(deviceVo.getDeviceId());
            return deviceVo;
        }
        return new DeviceVo();
    }


    @Override
    public void deleteDevice(DeleteDeviceRequest request) throws Exception {
        request.setIotInstanceId(iotInstanceId);
        DeleteDeviceResponse response = client.deleteDevice(request);
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            deviceMapper.deleteByDeviceId(request.getIotId());
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());
    }
}
